package com.yeyks.apppay.controller;

import com.yeyks.dal.domain.OrderInfo;
import com.yeyks.dal.domain.RechargeRecord;
import com.yeyks.dal.domain.VipOrder;
import com.yeyks.exception.ServiceException;
import com.yeyks.service.OrderService;
import com.yeyks.service.RechargeRecordService;
import com.yeyks.service.VipOrderService;
import com.yeyks.wxpay.WXPayUtil;
import com.yeyks.exception.ServiceException;
import com.yeyks.service.OrderService;
import com.yeyks.wxpay.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author fuchangshuai
 * @date 2019/3/11 1:48 PM
 */
@RestController
@Slf4j
public class WxPayCallbackController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private VipOrderService vipOrderService;
//    @Autowired
//    private RechargeRecordService rechargeRecordService;

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    @ApiIgnore
    @RequestMapping(value = "/wxPayCallback", method = RequestMethod.POST)
    public String wxPayCallback(HttpServletRequest request) {
        log.info("微信支付回调");
        try {
            // 读取参数
            // 解析xml成map
            Map<String, String> map = WXPayUtil.xmlToMap(getParam(request));
            log.info("微信支付回调返回的信息{}", map);
            check(map);
            String orderNo = map.get("out_trade_no");
            String resultCode = map.get("result_code");
            // 另起线程处理业务
            log.info("另起线程处理业务");
            executorService.execute(() -> {
                // 支付成功
                if (resultCode.equals("SUCCESS")) {
                    log.info("支付成功");
                    // 处理支付成功修改状态为待入住
                    orderService.payCallback(orderNo, true);
                } else {
                    log.info("支付失败");
                    orderService.payCallback(orderNo, false);
                }
            });
            if (resultCode.equals("SUCCESS")) {
                return setXml("SUCCESS", "OK");
            } else {
                return setXml("fail", "付款失败");
            }
        } catch (ServiceException e) {
            log.info("微信支付回调发生异常{}", e.getMessage());
            return setXml("fail", "付款失败");
        } catch (Exception e) {
            log.info("微信支付回调发生异常{}", e.getLocalizedMessage());
            return setXml("fail", "付款失败");
        }
    }

    @ApiIgnore
    @RequestMapping(value = "/wxPayCallbackV2", method = RequestMethod.POST)
    public String wxPayCallbackV2(HttpServletRequest request) {
        log.info("微信充值回调");
        try {
            // 解析xml成map
            Map<String, String> map = WXPayUtil.xmlToMap(getParam(request));
            log.info("微信充值回调返回的信息{}", map);
            checkV2(map);
            String orderNo = map.get("out_trade_no");
            String resultCode = map.get("result_code");
            // 另起线程处理业务
            log.info("另起线程处理业务");
            executorService.execute(() -> {
                // 支付成功
                if (resultCode.equals("SUCCESS")) {
                    log.info("支付成功");
                    vipOrderService.payCallback(orderNo, true);
                } else {
                    log.info("支付失败");
                    vipOrderService.payCallback(orderNo, false);
                }
            });
            if (resultCode.equals("SUCCESS")) {
                return setXml("SUCCESS", "OK");
            } else {
                return setXml("fail", "付款失败");
            }
        } catch (ServiceException e) {
            log.info("微信充值回调发生异常{}", e.getMessage());
            return setXml("fail", "付款失败");
        } catch (Exception e) {
            log.info("微信充值回调发生异常{}", e.getLocalizedMessage());
            return setXml("fail", "付款失败");
        }
    }

//    @ApiIgnore
//    @RequestMapping(value = "/rechangeCallback", method = RequestMethod.POST)
//    public String rechangeCallback(HttpServletRequest request) {
//        log.info("推广充值回调");
//        try {
//            // 解析xml成map
//            Map<String, String> map = WXPayUtil.xmlToMap(getParam(request));
//            log.info("推广充值回调返回的信息{}", map);
//            checkRechange(map);
//            String orderNo = map.get("out_trade_no");
//            String resultCode = map.get("result_code");
//            // 另起线程处理业务
//            log.info("另起线程处理业务");
//            executorService.execute(() -> {
//                // 支付成功
//                if (resultCode.equals("SUCCESS")) {
//                    log.info("支付成功");
//                    rechargeRecordService.payCallback(orderNo, true);
//                } else {
//                    log.info("支付失败");
//                    rechargeRecordService.payCallback(orderNo, false);
//                }
//            });
//            if (resultCode.equals("SUCCESS")) {
//                return setXml("SUCCESS", "OK");
//            } else {
//                return setXml("fail", "付款失败");
//            }
//        } catch (ServiceException e) {
//            log.info("推广充值回调发生异常{}", e.getMessage());
//            return setXml("fail", "付款失败");
//        } catch (Exception e) {
//            log.info("推广充值回调发生异常{}", e.getLocalizedMessage());
//            return setXml("fail", "付款失败");
//        }
//    }

    private String getParam(HttpServletRequest request) throws IOException {
        // 读取参数
        InputStream inputStream;
        StringBuilder sb = new StringBuilder();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        return sb.toString();
    }

    private void check(Map<String, String> params) throws ServiceException {
        String outTradeNo = params.get("out_trade_no");
        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        OrderInfo order = orderService.selectOrderByOrderNo(outTradeNo);
        if (order == null) {
            throw new ServiceException("out_trade_no错误");
        }

        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        Integer totalAmount = Integer.valueOf(params.get("total_fee"));
        log.info("totalAmount{}", totalAmount);
        if (!totalAmount.equals(order.getSnapshotTotalFee())) {
            throw new ServiceException("total_amount错误");
        }
    }

    private void checkV2(Map<String, String> params) throws ServiceException {
        String outTradeNo = params.get("out_trade_no");
        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        VipOrder order = vipOrderService.selectOrderByOrderNo(outTradeNo);
        if (order == null) {
            throw new ServiceException("out_trade_no错误");
        }

        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        Integer totalAmount = Integer.valueOf(params.get("total_fee"));
        log.info("totalAmount{}", totalAmount);
        if (!totalAmount.equals(order.getPayAmount())) {
            throw new ServiceException("total_amount错误");
        }
    }

//    private void checkRechange(Map<String, String> params) throws ServiceException {
//        String outTradeNo = params.get("out_trade_no");
//        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
//        RechargeRecord rechargeRecord = rechargeRecordService.selectOrderByOrderNo(outTradeNo);
//        if (rechargeRecord == null) {
//            throw new ServiceException("out_trade_no错误");
//        }
//
//        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
//        Integer totalAmount = Integer.valueOf(params.get("total_fee"));
//        log.info("totalAmount{}", totalAmount);
//        if (!totalAmount.equals(rechargeRecord.getPayAmount())) {
//            throw new ServiceException("total_amount错误");
//        }
//    }

    // 通过xml发给微信消息
    private static String setXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        try {
            return WXPayUtil.mapToXml(parameters);
        } catch (Exception e) {
            log.error("返回微信消息时map转xml失败");
            return "<xml><return_code><![CDATA[" + return_code + "]]>" + "</return_code><return_msg><![CDATA[" + return_msg
                    + "]]></return_msg></xml>";
        }
    }

}
